/*
 *  local.c
 *
 *  Copyright (C) 2011  Peter Polacik <polacik.p@gmx.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "alogd.h"

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <arpa/inet.h>

int recv_local(conf_t *prefs)
{
	int csockfd, tmp, len;
	char *buf, *msghdr;
	struct sockaddr_un name;
	struct mesg *applog;
	if ((sockfd = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
		errorize(strerror(errno), E_SOCK);
	name.sun_family = AF_LOCAL;
	strcpy(name.sun_path, prefs->sockpath);
	if (bind(sockfd, (const struct sockaddr *)&name, 
		 SUN_LEN(&name)) == -1)
		errorize(strerror(errno), E_BIND);
	if (listen(sockfd, prefs->backlog) == -1)
		errorize(strerror(errno), E_LISTEN);
#ifdef DEBUG
	fprintf(stderr, "[DEBUG] listening on socket : %d : %s\n", 
		sockfd, prefs->sockpath);
#endif
	while (1) {
		if ((csockfd = accept(sockfd, NULL, NULL)) != -1) {
			/*
			 * get_msg:
			 * 	reads message from socket, returns pointer
			 * 	to realloc(3) allocated buffer
			 */
			buf = get_msg(csockfd);
			len = strlen(buf);
			/*
			 * parse_msg:
			 * 	 similar to config file, but it 
			 * 	 doesn't parse actual config, but rather 
			 * 	 divides message read from socket into three
			 * 	 parts, the application's name (needed for 
			 * 	 file name etc.), type of message (integer, 
			 * 	 used by getmsghdr) and actual log message. 
			 * 	 It also should fix all dangerous characters
			 * 	 from application's name, so it's safe to use 
			 * 	 it in addapp for name of file
			 */
			applog = parse_msg(buf, len);
#ifdef DEBUG
			fprintf(stderr, "[DEBUG] progname @ %p : \'%s\'\n", 
				applog->progname, applog->progname);
			fprintf(stderr, "[DEBUG] type : %d\n", applog->type);
			fprintf(stderr, "[DEBUG] msg @ %p : \'%s\'\n", 
				applog->msg, applog->msg);
#endif
			if ((tmp = getfd(applog->progname)) == -1)
			/*
			 * addapp:
			 * 	  takes only one argument, the app name and it
			 * 	  prepares path itself, opens the file for
			 * 	  writing and returns actual file descriptor
			 */
				tmp = addapp(applog->progname, 
						prefs->logdir);
#ifdef DEBUG
			fprintf(stderr, "[DEBUG] fd (tmp) : %d\n", tmp);
#endif
			/*
			 * getmsghdr:
			 * 	 parses type number into header
			 * 	 string, that should be added into the 
			 * 	 beginning of each log message, based on
			 * 	 preferences set by user in some file (to be
			 * 	 added later) or, if none found (current 
			 * 	 case), the default ones
			 */
			msghdr = getmsghdr(applog->type);
			/*
			 * program_log:
			 * 	 the function, that actually
			 * 	 logs the message into the file. Arguments 
			 * 	 are, in following order: file descriptor,
			 * 	 message header, message body, flags. Fourth
			 * 	 argument (flags) can specify various OR-ed
			 * 	 values, modifying default behaviour of this
			 * 	 function (such sa LOG_DATE makes it log time
			 * 	 and date of function -> TO BE IMPLEMENTED). 
			 * 	 For full list of flags, with definitions, see
			 * 	 file logging.h. If you want to use default
			 * 	 behaviour, set flags to zero (0)
			 */
			program_log(tmp, msghdr, applog->msg, 0);
			free(buf);
			close(csockfd);
		}
	}
	return 0;
}
